﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using static PengSW.RuntimeLog.RL;

namespace PengSW.TcpService
{
    public class ConnectionPool
    {
        public ConnectionPool()
        {
            Connections.CollectionChanged += OnConnections_CollectionChanged;
        }

        private void OnConnections_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (Connection aConnection in e.NewItems) RegisteConnection(aConnection);
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (Connection aConnection in e.OldItems) UnregisteConnection(aConnection);
                    break;
            }
        }

        private ObservableCollection<Connection> Connections => Connection.AllConnections;

        public Connection GetConnection(string aHost, int aPort, Protocol aProtocol, string aName)
        {
            Connection aConnection = (from r in Connections where r.RemoteHost == aHost && r.RemotePort == aPort && r.IsConnected select r).FirstOrDefault();
            if (aConnection != null) return aConnection;
            L($"创建到[{aHost}:{aPort}]的连接[{aName}]……");
            aConnection = new Connection(aProtocol, aName);
            aConnection.WorkWith(aHost, aPort);
            return aConnection;
        }

        private void OnConnection_Connected(object sender, EventArgs e)
        {
            if (!(sender is Connection aConnection)) return;
            L($"Connection {aConnection} connected.");
        }

        private void OnConnection_Disconnected(object sender, EventArgs e)
        {
            if (!(sender is Connection aConnection)) return;
            L($"Connection {aConnection} disconnected.");
            aConnection.Dispose();
        }

        private void OnConnection_Clarify(Connection aConnection, string aInfo, int aLevel)
        {
            L(aInfo, aLevel);
        }

        private void OnConnection_Received(Connection aConnection, byte[] aBytes)
        {
            if (aBytes[0] != 'H')
                L($"Connection {aConnection} Received [{Encoding.ASCII.GetString(aBytes).Trim()}]:[{aBytes.BytesToString()}]。", 9);
        }

        protected void UnregisteConnection(Connection aConnection)
        {
            aConnection.Disconnected -= OnConnection_Disconnected;
            aConnection.Connected -= OnConnection_Connected;
            aConnection.Clarify -= OnConnection_Clarify;
            aConnection.Received -= OnConnection_Received;
        }

        protected void RegisteConnection(Connection aConnection)
        {
            aConnection.Disconnected += OnConnection_Disconnected;
            aConnection.Connected += OnConnection_Connected;
            aConnection.Clarify += OnConnection_Clarify;
            aConnection.Received += OnConnection_Received;
        }
    }
}
